package com.xuzimian.globaldemo.designpatterns.proxy.dynamic;


import com.xuzimian.globaldemo.designpatterns.proxy.ISubject;
import com.xuzimian.globaldemo.designpatterns.proxy.SubjectNoInterfaces;
import org.junit.jupiter.api.Test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import static java.lang.System.out;

public class JdkProxyTest {

    @Test
    public void test_Success() {

        ISubject target = new ISubject() {
            @Override
            public String processBusiness() {
                out.println("Method processBusiness call by JdkProxyDemo");
                return "Jdk";
            }
        };

        ISubject principalProxy = (ISubject) Proxy.newProxyInstance(ISubject.class.getClassLoader(),
                target.getClass().getInterfaces(), new JdkHandler(target));

        principalProxy.processBusiness();
    }

    @Test
    public void test_Fail() {
        SubjectNoInterfaces principal = (SubjectNoInterfaces) Proxy.newProxyInstance(SubjectNoInterfaces.class.getClassLoader(),
                SubjectNoInterfaces.class.getInterfaces(), new JdkHandler(new SubjectNoInterfaces()));

        principal.processBusiness();
    }
}

class JdkHandler implements InvocationHandler {
    private Object target;

    public JdkHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        doBefore();

        Object result = method.invoke(target, args);

        doAfter();

        return result;
    }

    private void doBefore() {
        out.println("Before ...");
    }

    private void doAfter() {
        out.println("After ...");
    }
}
